package cn.edu.tju.elm.service.impl;

import cn.edu.tju.core.model.User;
import cn.edu.tju.elm.dto.OrderCreateDto;
import cn.edu.tju.elm.dto.wallet.WalletOperationDto;
import cn.edu.tju.elm.model.*;
import cn.edu.tju.elm.repository.*;
import cn.edu.tju.elm.service.OrderService;
import cn.edu.tju.elm.service.WalletService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired private CartRepository cartRepository;
    @Autowired private BusinessRepository businessRepository;
    @Autowired private DeliveryAddressRepository addressRepository;
    @Autowired private OrderRepository orderRepository;
    @Autowired private OrderDetailetRepository orderDetailetRepository;
    @Autowired private WalletService walletService;

    @Override
    @Transactional // 开启事务！确保所有数据库操作要么全部成功，要么全部失败。
    public Order createOrder(OrderCreateDto orderDto, User customer) {
        
        if (orderDto.getBusiness() == null || orderDto.getBusiness().getId() == null) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "请求体中必须包含有效的 business.id");
        }
        if (orderDto.getDeliveryAddress() == null || orderDto.getDeliveryAddress().getId() == null) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "请求体中必须包含有效的 deliveryAddress.id");
        }
        
        Long businessId = orderDto.getBusiness().getId();
        Long addressId = orderDto.getDeliveryAddress().getId();
        
        // 1. 查找对应的商家和配送地址
        Business business = businessRepository.findById(businessId)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "商家不存在"));
        DeliveryAddress address = addressRepository.findById(addressId)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "配送地址不存在"));

        // 2. 从购物车中获取该用户在该商家的所有点餐项
        List<Cart> cartItems = cartRepository.findByCustomerIdAndBusinessId(customer.getId(), businessId);
        if (cartItems.isEmpty()) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "购物车为空，无法创建订单");
        }

        // 3. 计算订单总价
        BigDecimal orderTotal = cartItems.stream()
                .map(cart -> cart.getFood().getFoodPrice().multiply(new BigDecimal(cart.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
                
        // 检查商品总价是否达到起送价
        BigDecimal startPrice = business.getStartPrice() != null ? business.getStartPrice() : BigDecimal.ZERO;
        if (orderTotal.compareTo(startPrice) < 0) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, 
                "商品总价(" + orderTotal + ")未达到起送价(" + startPrice + ")");
        }
        
        // 加上配送费
        BigDecimal deliveryPrice = business.getDeliveryPrice() != null ? business.getDeliveryPrice() : BigDecimal.ZERO;
        orderTotal = orderTotal.add(deliveryPrice);


        // 4. 创建订单主记录 (Order)
        Order newOrder = new Order();
        newOrder.setCustomer(customer);
        newOrder.setBusiness(business);
        newOrder.setDeliveryAddress(address);
        newOrder.setOrderTotal(orderTotal);
        newOrder.setOrderDate(LocalDateTime.now());
        newOrder.setOrderState(1); // 1: 已下单(未支付)
        newOrder.setCreator(customer.getId());
        newOrder.setUpdater(customer.getId());
        newOrder.setCreateTime(LocalDateTime.now());
        newOrder.setUpdateTime(LocalDateTime.now());
        newOrder.setDeleted(false);
        // 保存订单主记录，这样它就有了ID
        Order savedOrder = orderRepository.save(newOrder);

        // 5. 遍历购物车项，创建订单详情记录 (OrderDetailet)
        for (Cart item : cartItems) {
            OrderDetailet detail = new OrderDetailet();
            detail.setOrder(savedOrder); // 关联到刚刚创建的订单
            detail.setFood(item.getFood());
            detail.setQuantity(item.getQuantity());
            orderDetailetRepository.save(detail);
        }

        // 6. 清空该用户在该商家的购物车
        cartRepository.deleteByCustomerIdAndBusinessId(customer.getId(), businessId);

        // 7. 下单时仅在商家侧预冻结入账金额（不扣顾客余额）
        try {
            Long businessOwnerId = business.getBusinessOwner().getId();
            if (!walletService.existsByUserId(businessOwnerId)) {
                walletService.createWallet(businessOwnerId, business.getBusinessOwner());
            }
            WalletOperationDto incomeFreeze = new WalletOperationDto();
            incomeFreeze.setUserId(businessOwnerId);
            incomeFreeze.setAmount(orderTotal);
            incomeFreeze.setOrderId(savedOrder.getId());
            incomeFreeze.setBusinessId(businessId);
            incomeFreeze.setRemark("订单入账预冻结 - 订单号：" + savedOrder.getId());
            incomeFreeze.setOperator(customer.getId());
            walletService.freezeIncome(incomeFreeze);
            // 订单保持为未支付(1)，由支付流程或支付页更新为已支付(2)
        } catch (Exception e) {
            throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "订单预冻结失败：" + e.getMessage());
        }

        // 9. 返回创建成功的订单
        return savedOrder;
    }

    @Override
    public Order getOrderById(Long orderId, User currentUser) {
        // 1. 根据ID查找订单，如果找不到则抛出 404 异常
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Order not found with ID: " + orderId));

        // 2. 权限检查
        boolean isAdmin = currentUser.getAuthorities().stream()
                .anyMatch(auth -> "ADMIN".equals(auth.getName()));
        
        // 检查当前用户是否是订单的顾客
        boolean isCustomer = order.getCustomer().getId().equals(currentUser.getId());
        
        // 检查当前用户是否是订单所属商家的店主
        boolean isBusinessOwner = order.getBusiness().getBusinessOwner().getId().equals(currentUser.getId());

        // 3. 如果不是管理员、不是顾客本人、也不是商家店主，则抛出权限不足的异常
        if (!isAdmin && !isCustomer && !isBusinessOwner) {
            throw new AccessDeniedException("您没有权限查看此订单");
        }

        // 4. 权限检查通过，返回订单信息
        return order;
    }

    @Override
    public List<Order> listOrdersForUser(User currentUser) {
        // 直接调用 Repository 中我们刚刚定义的新方法
        return orderRepository.findByCustomer_IdAndDeletedIsFalseOrderByOrderDateDesc(currentUser.getId());
    }

    // @Override
    // public List<Order> listOrdersForUser(User currentUser) {
    //     // 调用我们用 @Query 定义的、绝对可靠的新方法
    //     return orderRepository.findActiveOrdersForCustomer(currentUser.getId());
    // }

    @Override
    @Transactional
    public Order updateOrderStatus(Long orderId, Integer status, User currentUser) {
        // 1. 根据ID查找订单，如果找不到则抛出404异常
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "订单不存在"));

        // 2. 权限检查
        boolean isAdmin = currentUser.getAuthorities().stream()
                .anyMatch(auth -> "ADMIN".equals(auth.getName()));
        
        // 检查当前用户是否是订单的顾客
        boolean isCustomer = order.getCustomer().getId().equals(currentUser.getId());
        
        // 检查当前用户是否是订单所属商家的店主
        boolean isBusinessOwner = order.getBusiness().getBusinessOwner().getId().equals(currentUser.getId());

        // 3. 如果不是管理员、不是顾客本人、也不是商家店主，则抛出权限不足的异常
        if (!isAdmin && !isCustomer && !isBusinessOwner) {
            throw new AccessDeniedException("您没有权限更新此订单状态");
        }

        // 4. 验证状态值是否有效
        if (status < 0 || status > 4) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "无效的订单状态值");
        }

        // 5. 如果订单状态更新为已送达(4)，需要解冻并转账给商家
        // 商家制作完成(3)：扣顾客款并将商家入账预冻结转为实际冻结
        if (status == 3 && order.getOrderState() != 3) {
            try {
                BigDecimal orderTotal = order.getOrderTotal();
                Long customerId = order.getCustomer().getId();
                Long businessOwnerId = order.getBusiness().getBusinessOwner().getId();

                // 顾客扣款
                WalletOperationDto payOp = new WalletOperationDto();
                payOp.setUserId(customerId);
                payOp.setAmount(orderTotal);
                payOp.setOrderId(order.getId());
                payOp.setBusinessId(order.getBusiness().getId());
                payOp.setRemark("订单完成扣款 - 订单号：" + order.getId());
                payOp.setOperator(currentUser.getId());
                walletService.pay(payOp);

                // 商家入账预冻结转为实际冻结
                WalletOperationDto realizeOp = new WalletOperationDto();
                realizeOp.setUserId(businessOwnerId);
                realizeOp.setAmount(orderTotal);
                realizeOp.setOrderId(order.getId());
                realizeOp.setBusinessId(order.getBusiness().getId());
                realizeOp.setRemark("订单完成入账冻结 - 订单号：" + order.getId());
                realizeOp.setOperator(currentUser.getId());
                walletService.realizeIncomeToFrozen(realizeOp);

            } catch (Exception e) {
                throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "订单完成处理失败：" + e.getMessage());
            }
        }

        // 顾客确认收货(4)：解冻商家冻结金额至可用余额
        if (status == 4 && order.getOrderState() != 4) {
            try {
                BigDecimal orderTotal = order.getOrderTotal();
                Long businessOwnerId = order.getBusiness().getBusinessOwner().getId();

                WalletOperationDto unfreezeMerchant = new WalletOperationDto();
                unfreezeMerchant.setUserId(businessOwnerId);
                unfreezeMerchant.setAmount(orderTotal);
                unfreezeMerchant.setOrderId(order.getId());
                unfreezeMerchant.setBusinessId(order.getBusiness().getId());
                unfreezeMerchant.setRemark("确认收货解冻至商家余额 - 订单号：" + order.getId());
                unfreezeMerchant.setOperator(currentUser.getId());
                walletService.unfreeze(unfreezeMerchant);

            } catch (Exception e) {
                throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "确认收货处理失败：" + e.getMessage());
            }
        }

        // 6. 更新订单状态
        order.setOrderState(status);
        order.setUpdateTime(LocalDateTime.now());
        order.setUpdater(currentUser.getId());

        // 7. 保存并返回更新后的订单
        return orderRepository.save(order);
    }

    @Override
    public List<OrderDetailet> getOrderDetailets(Long orderId, User currentUser) {
        // 1. 权限检查：只有当前登录用户是订单的顾客、商家店主或管理员才能查看订单详情
        getOrderById(orderId, currentUser);
        
        // 2. 调用Repository查询订单详情
        return orderDetailetRepository.findByOrder_Id(orderId);
    }

    @Override
    public List<Order> listOrdersForBusiness(Long businessId, User currentUser) {
        // 管理员或商家所有者可以查看；这里简单允许已登录用户查看其所属商家的订单
        // 更严格的校验可根据业务补充
        return orderRepository.findByBusiness_IdAndDeletedIsFalseOrderByOrderDateDesc(businessId);
    }
}
